#include "Config.h"

#include <iostream>
#include <fstream>
#include <stdlib.h>

#include "io.h"

//#define DEBUG

Config *Config::s_instance = 0;

Config::Config()
{ initialize(); }

void Config::initialize(){ 
  initialize("settings.cfg");
}

void Config::initialize(string fileName)
{
  ifstream configfile(fileName.c_str());

  string line;
  while (! configfile.eof() )
  {
    getline(configfile, line);
    
    string name, value;
    split(removeWhitespaces(line), name, value, "=");
    
    // dataset //
    if(name.compare("databaseFilename") == 0)
      databaseFilename = value;
    else if(name.compare("imagesTrainPathname") == 0)
      imagesTrainPathname = value;
    else if(name.compare("wordsTrainPathname") == 0)
      wordsTrainPathname  = value;
    else if(name.compare("imagesTestPathname") == 0)
      imagesTestPathname  = value;
    else if(name.compare("wordsTestPathname") == 0)
      wordsTestPathname   = value;
    else if(name.compare("wordsOutputPathname") == 0)
      wordsOutputPathname = value;
     
    else if(name.compare("i") == 0)
      i = atoi(value.c_str()); 
    else if(name.compare("j") == 0)
      j = atoi(value.c_str()); 
    
    /*preprocessing*/
    else if(name.compare("threshold") == 0)
      threshold = atoi(value.c_str()); //to black/white
    else if(name.compare("minimumConnectedComponentSize") == 0)
      minimumConnectedComponentSize = atoi(value.c_str()); //ruis verwijdering
    
    /*segmentatie*/
    else if (name.compare("useGivenBoundariesWhenPossible") == 0)
      useGivenBoundariesWhenPossible = value.compare("true") == 0;
    else if(name.compare("lineSeperationDeviationWeightFactor") == 0)
      lineSeperationDeviationWeightFactor = atoi(value.c_str()); //distance to centre line
    else if(name.compare("lineSeperationWhitePixelWeight") == 0)
      lineSeperationWhitePixelWeight = atoi(value.c_str()); //white-passing
    else if(name.compare("lineSeperationBlackPixelWeight") == 0)
      lineSeperationBlackPixelWeight = atoi(value.c_str()); //black-passing
    
    else if(name.compare("wordSeperationHypotheseMinimumGapWidth") == 0)
      wordSeperationHypotheseMinimumGapWidth = atoi(value.c_str()); //
    else if(name.compare("wordSeperationHypotheseThresholdWidth") == 0)
      wordSeperationHypotheseThresholdWidth = atoi(value.c_str()); //
    else if(name.compare("wordSeperationOnlyLookBetweenBaseAndXLine") == 0)
      wordSeperationOnlyLookBetweenBaseAndXLine = value.compare("true") == 0; //removes top  //TODO: true is mooier, maar coordinaten goed krijgen is dan alleen kut
    else if(name.compare("wordSeperationUseShearedImage") == 0)
      wordSeperationUseShearedImage = value.compare("true") == 0; //the sheared image is the image with the original shear setting this to true doesnt work very well, the shearing messes stuf up
    
    else if(name.compare("maxGap") == 0)
      maxGap = atoi(value.c_str()); // gebruikt bij het on-overlappen, voor verwijderen woorden
    
    /*features*/
    else if(name.compare("applyWeightsBeforeSquaring") == 0)
      applyWeightsBeforeSquaring = value.compare("true") == 0;
    else if(name.compare("lowResolutionWordWidth") == 0)
      lowResolutionWordWidth = atoi(value.c_str());
    else if(name.compare("lowResolutionWordHeight") == 0)
      lowResolutionWordHeight = atoi(value.c_str());
    
    else if(name.compare("bottomProfileSampleNumber") == 0)
      bottomProfileSampleNumber = atoi(value.c_str());

    else if(name.compare("radonanglecount") == 0)
      radonanglecount = atoi(value.c_str());
    else if(name.compare("radonlinecount") == 0)
      radonlinecount  = atoi(value.c_str());
    else if(name.compare("radonhistowidth") == 0)
      radonhistowidth = atoi(value.c_str());
    
    else if(name.compare("maxWordLengthDifference") == 0)
      maxWordLengthDifference = atoi(value.c_str()); //percentage
    
    else if(name.compare("wordLengthDifferenceWeight") == 0)
      wordLengthDifferenceWeight = atoi(value.c_str());
    else if(name.compare("radonDistanceWeight") == 0)
      radonDistanceWeight = atoi(value.c_str());
    else if(name.compare("bottomProfileDistanceWeight") == 0)
      bottomProfileDistanceWeight = atoi(value.c_str());
    else if(name.compare("heightWidthRatioWeight") == 0)
      heightWidthRatioWeight = atoi(value.c_str());
    else if(name.compare("lowResolutionWordDistanceWeight") == 0)
      lowResolutionWordDistanceWeight = atoi(value.c_str());
    
    /*testing*/
    else if(name.compare("thresholddistance") == 0)
      thresholddistance = atoi(value.c_str()); //voordat een woordzone goed matcht
 #ifdef DEBUG
    else
      cout << "line = [" << line << "] with name = [" << name << "] and value = [" << value << "] ignored." << endl;
#endif
  }
#ifdef DEBUG
  cout << "is this right? (y/n) " << endl;
  char ans;
  cin >> ans;
  if(ans == 'n')
    throw 42;
#endif
}

string Config::removeWhitespaces(string line)
{
  string returnLine = "";
  for(size_t idx = 0; idx < line.length(); idx++)
    if(line[idx] == '"')
      continue;
    else if(line[idx] == ';')
      return returnLine;
    else if(idx + 1 < line.length() && line[idx] == '/' && line[idx + 1] == '/')
      return returnLine;
    else if(!isspace(line[idx]))
      returnLine += line[idx];
  return returnLine;
}

void Config::split(string line, string& name, string& value, string seperator)
{ //0123456789
  //name=value 
  size_t idx = line.find(seperator); //if seperator == "=", then idx = 5
  name = line.substr(0, idx); //name = "name"
  value = line.substr(idx + 1); //value = "value"
}

Config* Config::getInstance()
{
  //static Config s_instance;
  if(!s_instance)
    s_instance = new Config;
  return s_instance;
  
}
